package com.fulihui.wgj.service.wxuser;

import com.alibaba.dubbo.config.annotation.Service;
import com.alibaba.fastjson.JSON;
import com.fulihui.common.builder.rpc.RpcResultBuilder;
import com.fulihui.common.conv.BeanConv;
import com.fulihui.common.error.Errors;
import com.fulihui.common.error.InvokeServiceException;
import com.fulihui.common.result.rpc.BaseResult;
import com.fulihui.common.result.rpc.SimpleResult;
import com.fulihui.common.util.Base64Utils;
import com.fulihui.common.util.ConditionValidator;
import com.fulihui.common.util.PlatformUtil;
import com.fulihui.weixinsdk.WeixinSDK;
import com.fulihui.weixinsdk.model.Article;
import com.fulihui.weixinsdk.model.NewsMessage;
import com.fulihui.weixinsdk.request.customer.CustomerNewsMsgRequest;
import com.fulihui.weixinsdk.result.customer.CustomerNewsMsgResult;
import com.fulihui.wgj.biz.SendHistoryUserBiz;
import com.fulihui.wgj.dal.impala.domain.WxUserInfo;
import com.fulihui.wgj.dal.impala.mapper.UserInfoMapper;
import com.fulihui.wgj.dal.mybatis.domain.Wx48NewsInfo;
import com.fulihui.wgj.dal.mybatis.domain.WxHistorySendUser;
import com.fulihui.wgj.dal.mybatis.domain.WxRegion;
import com.fulihui.wgj.dal.mybatis.repository.Wx48NewsInfoRepository;
import com.fulihui.wgj.dal.mybatis.repository.WxHistorySendUserRepository;
import com.fulihui.wgj.dal.mybatis.repository.WxRegionRepository;
import com.fulihui.wgj.facade.dto.WxHistorySendUserDTO;
import com.fulihui.wgj.facade.dto.WxUserInfoDTO;
import com.fulihui.wgj.facade.request.wx48.WxUserInfoSendSingle48HRequest;
import com.fulihui.wgj.facade.request.wxuser.WxHistorySendUserQueryRequest;
import com.fulihui.wgj.facade.request.wxuser.WxHistorySendUserSaveRequest;
import com.fulihui.wgj.facade.request.wxuser.WxUserInfoPreviewQueryRequest;
import com.fulihui.wgj.facade.service.wxuser.WxUserInfoService;
import com.google.common.base.Stopwatch;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * @author wang_wx
 * @date 2018-06-14
 */
@Component
@Service(interfaceClass = WxUserInfoService.class, version = "1.0.0")
public class WxUserInfoServiceImpl implements WxUserInfoService {

    private static final Logger LOGGER = LoggerFactory.getLogger(WxUserInfoServiceImpl.class);

    @Autowired
    private UserInfoMapper userInfoMapper;

    @Autowired
    private WxRegionRepository wxRegionRepository;

    @Autowired
    private PlatformUtil platformUtil;

    @Autowired
    private Wx48NewsInfoRepository wx48NewsInfoRepository;

    @Autowired
    private WeixinSDK weixinSDK;

    @Autowired
    private SendHistoryUserBiz sendHistoryUserBiz;

    @Autowired
    private WxHistorySendUserRepository wxHistorySendUserRepository;

    @Override
    public BaseResult sendSingleUserWx48H(WxUserInfoSendSingle48HRequest request) throws InvokeServiceException {
        ConditionValidator.validate(request);
        String appId = request.getAppId();
        String openid = request.getOpenid();
        Long newsId = request.getNewsId();
        Wx48NewsInfo wx48NewsInfo = wx48NewsInfoRepository.queryById(newsId);
        if (Objects.isNull(wx48NewsInfo)) {
            return RpcResultBuilder.fail(Errors.Wx48HError.WX48_HOURS_MESSAGE_NOT_FOUND);
        }
        String accessToken = platformUtil.get(appId);
        if (StringUtils.isBlank(accessToken)) {
            return RpcResultBuilder.fail(Errors.Commons.TOKEN_DOES_NOT_EXIST);
        }
        String xmlContent = wx48NewsInfo.getXmlContent();
        NewsMessage newsMessage = JSON.parseObject(xmlContent, NewsMessage.class);
        String msgtype = newsMessage.getMsgtype();
        List<Article> articles = newsMessage.getNews().getArticles();
        Map<String, List<Article>> news = Maps.newHashMap();
        news.put("articles", articles);
        // 发送客服消息
        CustomerNewsMsgRequest newsMsgRequest = new CustomerNewsMsgRequest();
        newsMsgRequest.setAccess_token(accessToken);
        newsMsgRequest.setMsgtype(msgtype);
        newsMsgRequest.setNews(news);
        newsMsgRequest.setTouser(openid);
        CustomerNewsMsgResult customerNewsMsgResult = weixinSDK.invokeService(newsMsgRequest);
        // 如果发送成功 往预览历史用户表插入
        try {
            if (customerNewsMsgResult.isSuccess()) {
                WxHistorySendUserSaveRequest wxHistorySendUserSaveRequest = new WxHistorySendUserSaveRequest();
                wxHistorySendUserSaveRequest.setAppId(appId);
                wxHistorySendUserSaveRequest.setOpenid(openid);
                sendHistoryUserBiz.saveHistorySendUser(wxHistorySendUserSaveRequest);
            }
        } catch (Exception e) {
            LOGGER.error("saveHistorySendUser error" + e);
        }

        return customerNewsMsgResult.isSuccess() ? RpcResultBuilder.succ() : RpcResultBuilder.fail(Integer.valueOf(customerNewsMsgResult.getErrcode()), customerNewsMsgResult.getErrmsg());
    }

    @Override
    public SimpleResult<List<WxUserInfoDTO>> queryWxUserPreview(WxUserInfoPreviewQueryRequest request) throws InvokeServiceException {
        Stopwatch started = Stopwatch.createStarted();
        ConditionValidator.validate(request);
        List<WxUserInfo> wxUserInfos = userInfoMapper.query(request.getAppId(), builderQuery(request));
        List<WxUserInfoDTO> userInfoDTOS = null;
        if (!CollectionUtils.isEmpty(wxUserInfos)) {
            userInfoDTOS = BeanConv.copy(wxUserInfos, WxUserInfoDTO.class);
            // 转换区域为中文
            userInfoDTOS.stream().forEach(wxUserInfoDTO -> {
                String country = wxUserInfoDTO.getCountry();
                String province = wxUserInfoDTO.getProvince();
                String city = wxUserInfoDTO.getCity();
                WxRegion countryWxRegion = wxRegionRepository.queryWxRegionByRid(country);
                wxUserInfoDTO.setCountry(Objects.nonNull(countryWxRegion) ? countryWxRegion.getName() : null);
                WxRegion provinceWxRegion = wxRegionRepository.queryWxRegionByRid(province);
                wxUserInfoDTO.setProvince(Objects.nonNull(provinceWxRegion) ? provinceWxRegion.getName() : null);
                WxRegion cityWxRegion = wxRegionRepository.queryWxRegionByRid(city);
                wxUserInfoDTO.setCity(Objects.nonNull(cityWxRegion) ? cityWxRegion.getName() : null);
            });
        }
        long elapsed = started.elapsed(TimeUnit.MILLISECONDS);
        LOGGER.info("userInfoDTOS = [{}],耗时=[{}]", userInfoDTOS, elapsed);
        return RpcResultBuilder.succSimple(userInfoDTOS);
    }

    /**
     * 组装条件
     *
     * @param request
     * @return
     */
    private String builderQuery(WxUserInfoPreviewQueryRequest request) {
        StringBuffer column = new StringBuffer(" 1=1 ");
        String nickname = request.getNickname();
        column.append(" AND nickname like '%").append(nickname).append("%'");
        return column.toString();
    }

    @Override
    public SimpleResult<List<WxHistorySendUserDTO>> queryHistorySendUser(WxHistorySendUserQueryRequest request) throws InvokeServiceException {
        ConditionValidator.validate(request);
        WxHistorySendUser wxHistorySendUserQuery = new WxHistorySendUser();
        wxHistorySendUserQuery.setAppId(request.getAppId());
        List<WxHistorySendUser> wxHistorySendUsers = wxHistorySendUserRepository.queryByWhere(wxHistorySendUserQuery);
        List<WxHistorySendUserDTO> dtoList = null;
        if (!CollectionUtils.isEmpty(wxHistorySendUsers)) {
            dtoList = Lists.newArrayList();
            List<WxHistorySendUserDTO> finalDtoList = dtoList;
            wxHistorySendUsers.stream().forEach(wxHistorySendUser -> {
                WxHistorySendUserDTO userDTO = BeanConv.copy(wxHistorySendUser, WxHistorySendUserDTO.class);
                //处理emoji表情昵称的解码
                userDTO.setNickname(Base64Utils.decode(wxHistorySendUser.getNickname()));
                finalDtoList.add(userDTO);
            });
        }
        return RpcResultBuilder.succSimple(dtoList);
    }

}
